package leetcode.每日一题;

import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author :songyaozhang
 * @date :Created 2021/7/16 10:21
 * @description :
 */
public class Test {

    private List<WhiteSize> whiteSizes = null;

    private List<Float> proportions = new ArrayList<Float>();
    private Map<Float, List<int[]>> whitelist = new HashMap<Float, List<int[]>>();

    public static void main(String[] args) {
        Test test = new Test();
        //int[] ints = test.mapWhiteSize(500, 300);
        //System.out.println(Arrays.toString(ints));
        test.testAll();
    }

    /**
     * 测试全部数据
     */
    public void testAll() {
        init();
        //大数据测试
        int res = 0;
        int count = 0;
        int maxDiff = Integer.MIN_VALUE;
        long startTime = System.currentTimeMillis();
        for (int i = 100; i <= 750; i++) {
            for (int j = 100; j <= 480; j++) {
                    int w = i;
                    int h = j;
                    int[] ans = searchClosest(w, h);
                    /*int diff = ans[0] * ans[1] - w * h;
                    res += diff;
                    maxDiff = Math.max(maxDiff, diff);

                    count++;*/
                    System.out.println("[" + w + ", " + h + "]" + "\t" + (ans == null ? null : Arrays.toString(ans)));
                    /*if (diff == 22000) {
                        return;
                    }*/
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("总共耗时:" + (endTime - startTime) + "ms");
        System.out.println("最大像素差：" + maxDiff);
        //System.out.println("最大像素差元素：" + "[100, 100]  [200, 160]");
        System.out.println("平均像素差：" + (double) res / count);
    }

    private void init() {
        if (whiteSizes != null) {
            for (WhiteSize whiteSize : whiteSizes) {
                List<int[]> list = whitelist.getOrDefault(whiteSize.aspectRatio, new ArrayList<>());
                if (!whitelist.containsKey(whiteSize.aspectRatio)) {
                    proportions.add(whiteSize.aspectRatio);
                }
                list.add(new int[]{whiteSize.width, whiteSize.height});
                whitelist.put(whiteSize.aspectRatio, list);
            }
        }
    }
    /**
     * 返回映射后的白名单尺寸
     *
     * @param width  原始图片宽度
     * @param height 原始图片高度
     * @return 宽，高
     */
    private int[] mapWhiteSize(int width, int height) {
        //初始化白名单
        init();
        int[] ans = searchClosest(width, height);
        return ans == null ? null : ans;
    }

    private int[] searchClosest(int w, int h) {
        float proportion = (float) w / h;
        if (proportions.size() <= 0) {
            throw new RuntimeException("未初始化白名单");
        }
        proportions.sort(Float :: compare);
        int left =  binarySearch(proportion);
        //查找出了比例接近的集合
        float[] floats = new float[3];
        Arrays.fill(floats, Float.MAX_VALUE);
        if (left != -1) {
            float[] ans1 = find(whitelist.get(proportions.get(left)), w, h);
            float[] ans2;
            ans2 = left + 1 < whitelist.size() ? find(whitelist.get(proportions.get(left + 1)), w, h) : null;
            if (ans2 != null || ans1 != null) {
                float[] ans = (ans1 == null ? Double.MAX_VALUE : ans1[0])
                        > (ans2 == null ? Double.MAX_VALUE : ans2[0])
                        ? ans2 : ans1;
                floats[0] = ans[0];
                floats[1] = ans[1];
                floats[2] = ans[2];
            } else {
                for (Float pro : proportions) {
                    List<int[]> sizes = whitelist.get(pro);
                    float[] curAns = find(sizes, w, h);
                    if (curAns == null) continue;
                    if (curAns[0] < floats[0]) {
                        floats[0] = curAns[0];
                        floats[1] = curAns[1];
                        floats[2] = curAns[2];
                    }
                }
            }
        }
        if (floats[0] == Float.MAX_VALUE) {
            return null;
        } else {
            int[] ans = new int[2];
            ans[0] = (int) floats[1];
            ans[1] = (int) floats[2];
            return ans;
        }
    }

    private float[] find(List<int[]> sizes, int w, int h) {
        float[] min = new float[3];
        int maxDiff = Integer.MAX_VALUE;
        Arrays.fill(min, Float.MAX_VALUE);
        for (int[] size : sizes) {
            int curW = size[0];
            int curH = size[1];
            if (curW < w || curH < h) continue;
            int areaDiff = Math.abs(curW * curH - w * h);
            if (areaDiff < maxDiff) {
                float rate = Math.abs((float) curW / curH - (float) w / h);
                maxDiff = areaDiff;
                min[0] = rate;
                min[1] = curW;
                min[2] = curH;
            }
        }
        return min[0] == Float.MAX_VALUE ? null : min;
    }

    /**
     * 查询小于等于proportion的最大值
     * @param proportion
     * @return
     */
    private int binarySearch(double proportion) {
        int l = 0;
        int r = proportions.size() - 1;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (proportions.get(mid) <= proportion) {
                l = mid;
            } else {
                r = mid - 1;
            }
        }
        return proportions.get(r) <= proportion ? r : -1;
    }

    private static class WhiteSize {
        private Integer width;
        private Integer height;
        private Float aspectRatio;

        public Integer getWidth() {
            return width;
        }

        public void setWidth(Integer width) {
            this.width = width;
        }

        public Integer getHeight() {
            return height;
        }

        public void setHeight(Integer height) {
            this.height = height;
        }

        public Float getAspectRatio() {
            return aspectRatio;
        }

        public void setAspectRatio(Float aspectRatio) {
            this.aspectRatio = aspectRatio;
        }
    }
}
